package model;

import model.characterStanceTypes.CharacterStanceType;
import model.characterStanceTypes.CharacterStanceTypeRun;

public class Character {
	
	private String name;
	private CharacterStanceType stance;
	private int xLocation;
	private int yLocation;
	
	public Character() {
		stance = new CharacterStanceTypeRun();
		xLocation = 0;
		yLocation = 0;
	}

	public CharacterStanceType getStance() {
		return stance;
	}

	public void setStance(CharacterStanceType stance) {
		this.stance = stance;
	}

	public int getxLocation() {
		return xLocation;
	}

	public void setxLocation(int xLocation) {
		this.xLocation = xLocation;
	}

	public int getyLocation() {
		return yLocation;
	}

	public void setyLocation(int yLocation) {
		this.yLocation = yLocation;
	}
	
	public boolean[][] getVisibilityGrid(MapGrid map) {
		int gridSize = stance.getViewDistance() * 2 + 1;
		int numIterations = stance.getViewDistance();
		float visibilityGrid[][] = new float[gridSize][gridSize];
		boolean returnGrid[][] = new boolean[gridSize][gridSize];
		int centerCoord = numIterations;
		MapGrid gameMap = map;
		
		Point2D worldCoord;
		Point2D gridCoord;
		
		//calculate initial 4 directions
		for (int i = 1; i <= stance.getViewDistance(); i++) {
			
			//Left
			gridCoord = new Point2D(centerCoord - i, centerCoord);
			worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
			visibilityGrid[gridCoord.x][gridCoord.y] = gameMap.getVisibilityAt(worldCoord.x, worldCoord.y) + visibilityGrid[gridCoord.x + 1][gridCoord.y];
			
			//Right
			gridCoord = new Point2D(centerCoord + i, centerCoord);
			worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
			visibilityGrid[gridCoord.x][gridCoord.y] = gameMap.getVisibilityAt(worldCoord.x, worldCoord.y) + visibilityGrid[gridCoord.x - 1][gridCoord.y];
			
			//Up
			gridCoord = new Point2D(centerCoord, centerCoord - i);
			worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
			visibilityGrid[gridCoord.x][gridCoord.y] = gameMap.getVisibilityAt(worldCoord.x, worldCoord.y) + visibilityGrid[gridCoord.x][gridCoord.y + 1];
			
			//Down 
			gridCoord = new Point2D(centerCoord, centerCoord + i);
			worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
			visibilityGrid[gridCoord.x][gridCoord.y] = gameMap.getVisibilityAt(worldCoord.x, worldCoord.y) + visibilityGrid[gridCoord.x][gridCoord.y - 1];
		}
		
		for (int i = 1; i <= stance.getViewDistance(); i++) {
			
			for (int j = 1; j <= stance.getViewDistance(); j++) {
				
				//UpperLeftArea
				gridCoord = new Point2D(centerCoord - i, centerCoord - j);
				worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
				visibilityGrid[gridCoord.x][gridCoord.y] = (((visibilityGrid[gridCoord.x + 1][gridCoord.y] + visibilityGrid[gridCoord.x][gridCoord.y + 1]) / 2) + gameMap.getVisibilityAt(worldCoord.x, worldCoord.y));
				
				//UpperRightArea
				gridCoord = new Point2D(centerCoord - i, centerCoord + j);
				worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
				visibilityGrid[gridCoord.x][gridCoord.y] = (((visibilityGrid[gridCoord.x - 1][gridCoord.y] + visibilityGrid[gridCoord.x][gridCoord.y + 1]) / 2) + gameMap.getVisibilityAt(worldCoord.x, worldCoord.y));
				
				//LowerLeftArea
				gridCoord = new Point2D(centerCoord + i, centerCoord - j);
				worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
				visibilityGrid[gridCoord.x][gridCoord.y] = (((visibilityGrid[gridCoord.x + 1][gridCoord.y] + visibilityGrid[gridCoord.x][gridCoord.y - 1]) / 2) + gameMap.getVisibilityAt(worldCoord.x, worldCoord.y));
				
				//LowerRightArea
				gridCoord = new Point2D(centerCoord + i, centerCoord + j);
				worldCoord = translateGridCoordToMapCoords(gridCoord.x, gridCoord.y, gridSize);
				visibilityGrid[gridCoord.x][gridCoord.y] = (((visibilityGrid[gridCoord.x - 1][gridCoord.y] + visibilityGrid[gridCoord.x][gridCoord.y - 1]) / 2) + gameMap.getVisibilityAt(worldCoord.x, worldCoord.y));
			}
		}
		
		for (int i = 0; i < gridSize; i++) {
			for (int j = 0; j < gridSize; j++) {
				returnGrid[i][j] = (visibilityGrid[i][j] < stance.getViewDistance());
			}
		}
		
		
		return returnGrid;		
	}
	
	private Point2D translateGridCoordToMapCoords(int x, int y, int gridSize) {
		Point2D toReturn = new Point2D();
		int halfGrid = (gridSize - 1) / 2;
		toReturn.x = (xLocation - (halfGrid - x));
		toReturn.y = (yLocation - (halfGrid - y));
		return toReturn;
	}
	
	private class Point2D {
		public int x;
		public int y;
		
		public Point2D() {
			
		}
		public Point2D(int x, int y) {
			this.x = x;
			this.y = y;
		}
	}
}
